package com.raising.framework.exception;

import com.raising.framework.entity.ResultCode;
import com.raising.framework.entity.ResultVo;
import com.raising.modules.sys.entity.Elog;
import com.raising.modules.sys.service.ElogService;
import com.raising.utils.*;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.UncategorizedSQLException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 异常统一处理器
 * @author GaoYuan
 * @date 2019/1/17 上午11:56
 */
@ControllerAdvice
public class MyExceptionHandler {

    @Autowired
    ElogService elogService;


    final private SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @ExceptionHandler(value = {Exception.class,UncategorizedSQLException.class})
    public String defaultHandler(HttpServletRequest request, HttpServletResponse response, final Exception e){
        String errorContent = "";
        try{
            //当前用户
            String userId = UserUtils.getUserId();
            String nowDate = df.format(new Date());
            String uri = request.getRequestURI();
            String errorMessage = e.getMessage();
            if(StringUtils.isBlank(errorMessage)){
                errorMessage = e.toString();
            }
            if(errorMessage != null && errorMessage.length()>100){
                errorMessage = errorMessage.substring(0,100);
            }
            errorContent = getStackTraceAsString(e);
            if(errorContent != null){
                errorContent = errorContent.trim();
            }
            String ip = HttpUtils.getIpAddress(request);
            String userAgent = UserAgentUtils.getUserAgent(request).toString();
            String requestParam = HttpUtils.getParamsChar(request);
            String requestBody = HttpUtils.getRequestBodyChar(request);
            String requestMethod = HttpUtils.getRequestMethod(request);

            final Elog elog = new Elog();
            elog.setUserId(userId);
            elog.setErrorTime(nowDate);
            elog.setUri(uri);
            elog.setErrorMessage(errorMessage);
            elog.setErrorContent(errorContent);
            elog.setIp(ip);
            elog.setUserAgent(userAgent);
            if(requestParam != null && requestParam.length() > 100){
                requestParam = requestParam.substring(0,99);
            }
            elog.setRequestParam(requestParam);
            elog.setRequestBody(requestBody);
            elog.setRequestMethod(requestMethod);

            //这里入库
            JThreadUtils.pool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        elogService.insert(elog);
                    }catch (Exception e){e.printStackTrace();}
                }
            });
        }catch (Exception e2){

        }

        // 如果是没有权限访问
        if(e instanceof UnauthorizedException){
            // 如果是ajax
            if(RequestUtils.isAjax(request)){
                return renderString(response,ResultVo.failure(ResultCode.NO_PERMISSIONS).desc("无权限访问"));
            }
            // 未授权
            return "error/401";
        }

        //如果是ajax错误
        if (RequestUtils.isAjax(request)) {
            return renderString(response,ResultVo.error().desc("系统内部错误").data(errorContent));
        }
        request.setAttribute("errorContent", errorContent);
        return "error/500";
    }


    /**
     * 客户端返回JSON字符串
     *
     * @param response
     * @param object
     * @return String
     */
    protected String renderString(HttpServletResponse response, Object object) {
        JSONObject json = JSONObject.fromObject(object);
        return renderString(response, json.toString(), "application/json");
    }

    /**
     * 客户端返回字符串
     *
     * @param response
     * @param string
     * @return
     */
    protected String renderString(HttpServletResponse response, String string,
                                  String type) {
        try {
            response.reset();
            response.setContentType(type);
            response.setCharacterEncoding("utf-8");
            response.getWriter().print(string);
            response.getWriter().close();
            return null;
        } catch (IOException e) {
            return null;
        } finally {
            try {
                if(response!=null && response.getWriter() != null){
                    response.getWriter().close();
                }
            }catch (Exception e){}
        }
    }


    /**
     * 将ErrorStack转化为String.
     */
    public static String getStackTraceAsString(Throwable e) {
        if (e == null){
            return "";
        }
        StringWriter stringWriter = new StringWriter();
        e.printStackTrace(new PrintWriter(stringWriter));
        return stringWriter.toString();
    }
}
